require 'event_editor/commands/play_se'
require 'event_editor/commands/wait'
require 'event_editor/commands/switch'
require 'event_editor/character_select_dialog'
require 'event_editor/route/move_wait_dialog'
require 'event_editor/route/set_speed_dialog'
require 'event_editor/route/anime_dialog'
require 'event_editor/route/pass_dialog'
require 'event_editor/route/move'

module EventEditor
  module Commands
    class Route
      @command_names = {
      'wait' => "Wait",
      'anime' => "Anime",
      'pass' => "Pass",
      'switch' => "Switch",
      'set_graphic' => "Set Graphic",
      'dir_fix' => "Dir Fix",
      'dir_free' => "Dir Free",
      'speed_up' => "Speed Up",
      'visible' => "Visible",
      'invisible' => "Invisible",
      'speed_down' => "Speed Down"
      }

      @face_arr = [[0, -1, 'up'], [1, 0, 'right'], [0, 1, 'down'], [-1, 0, 'left']]
      @face_rotate_arr = [[-1, '-90'], [1, '+90']]
      @move_arr = [[0, -1, 'up'], [1, 0, 'right'], [0, 1, 'down'], [-1, 0, 'left'],
                    [1, -1, 'upper right'], [1, 1, 'bottom right'], [-1, 1, 'bottom left'], [-1, -1, 'upper left']]
                        
       def self.show(base, model, edit_command = [], options = {}, &func)
         if options[:static]
          @dynamic = false
         else
          @dynamic = true
         end
         @dialog = Gtk::Dialog.new("Route",
                 base,
                 Gtk::Dialog::MODAL,
                 ["OK", Gtk::Dialog::RESPONSE_OK],
                 ["Cancel", Gtk::Dialog::RESPONSE_CANCEL]
                 )

          @model = model
          
          # init components
          @list_model = Gtk::ListStore.new(String, Array)
          
          vbox = Gtk::VBox.new
          scrolled_window = Gtk::ScrolledWindow.new
          @list_box = Gtk::TreeView.new(@list_model)
          @list_box.selection.mode = Gtk::SELECTION_MULTIPLE
          @list_box.enable_search = false
                  
          @list_box.signal_connect('key-press-event') do |widget, event|
            if event.keyval == 65535
              self.delete_commands
            end
          end
          
          self.add_columns(@list_box)
          scrolled_window.add(@list_box)
          
          if @dynamic
            @event_combobox = ::Gadgets::Combobox.new(@model.event_select_list, [String, Integer])
            vbox.pack_start(@event_combobox, false, false)
          end
          
          vbox.add(scrolled_window)
          vbox.pack_start(@route_skip_check = Gtk::CheckButton.new('Skip when interrupted'), false, false)
          vbox.pack_start(@route_repeat_check = Gtk::CheckButton.new('Repeat'), false, false)
          
          if @dynamic
            vbox.pack_start(@wait_check = Gtk::CheckButton.new('Wait'), false, false)
          end
          
          # packing
          @dialog.set_size_request(600, 450)
          hbox = Gtk::HBox.new(false, 5)
          hbox.set_border_width(5)
          @list_box.set_width_request(250)
          hbox.pack_start(vbox, false, false)
          hbox.add(self.create_commands_panel)

          @dialog.vbox.add(hbox)
          @dialog.vbox.show_all
        
          self.load(edit_command)
          
          # run
          @dialog.run do |response|
          command = @dynamic ? self.command : self.static_command
          if response == Gtk::Dialog::RESPONSE_OK
            func.call(command)
          end
          @dialog.destroy
          end
        end

        def self.add_columns(treeview)
          renderer = Gtk::CellRendererText.new
          column = Gtk::TreeViewColumn.new('Route', renderer, :markup => 0)
          column.sizing = Gtk::TreeViewColumn::FIXED
          column.fixed_width = 50
          treeview.append_column(column)
        end
        
        def self.add_button(parent, name, command, &func)
          b = Gtk::Button.new(name)
          
          unless command
            b.sensitive = false
            parent.add(b)
            return
          end
          
          b.signal_connect('clicked') do
            copy_command = command
            if func
              copy_command = command.clone
              func.call(copy_command)
            end
            self.add_command(copy_command) unless copy_command.empty?
          end
          parent.add(b)
        end
        
        def self.delete_commands

          while true
            b = false
            @list_box.selection.selected_each do |model, path, iter| 
              break if iter == @last_iter
              b = true;
              @list_model.remove(iter) 
              break
            end
            break unless b
          end
        end
        
        def self.add_command(command)
          selected = nil
          @list_box.selection.selected_each {|model, path, iter| selected = iter; break;}
          
          unless selected
            @list_box.selection.select_iter(@last_iter)
            selected = @last_iter
          end
          
          if selected
            name = self.get_command_name(command)
            iter = @list_model.insert_before(selected)
            iter[0] = "* " + name
            iter[1] = command
          end
        end

        def self.get_command_name(command)
          case command[0]
            when 'move'
              return EventEditor::Route::Move.command_to_s(command) + " "

            when 'set_graphic'
              return @command_names[command[0]] + " " + command[1].to_s + ", " + command[2].to_s + ", " + command[3].to_s
            
            when 'switch'
              return Switch.command_to_s(@model, command, "")
            
            when 'play_se'
              return PlaySe.command_to_s(@model, command, "")
              
            when 'wait'
              return @command_names[command[0]] + " " + command[1].to_s
            
            when 'anime'
              return EventEditor::Route::AnimeDialog.command_to_s(command)
              
            when 'move_wait'
              return EventEditor::Route::MoveWaitDialog.command_to_s(command)
              
            when 'set_speed'
              return EventEditor::Route::SetSpeedDialog.command_to_s(command)
              
            when 'pass'
              return EventEditor::Route::PassDialog.command_to_s(command)

            else
              return @command_names[command[0]]
          end
        end

        def self.copy_arr(arr1, arr2)
          arr1.clear
          arr2.each do |value|
            arr1 << value
          end
        end
        
        def self.create_commands_panel
          box = Gtk::HBox.new(true, 5)
          
          vbox = Gtk::VBox.new(true, 2)
          
          self.add_button(vbox, 'Move', ['move']) do |arr|
            arr.clear
            EventEditor::Route::Move.show(@dialog) do |command|
              if command == :cancel
                arr.clear
              else
                self.copy_arr(arr, command)
              end
            end
          end
          
          
          #Set Graphic
          self.add_button(vbox, 'Set Graphic', ['set_graphic']) do |arr|
            arr.clear
            
            CharacterSelectDialog.show(@dialog, @model, nil, 0, 0) do |chip_id, frame_no, dir|
              arr << 'set_graphic'
              arr << chip_id
              arr << frame_no
              arr << dir
            end
          end
          
          #Switch
          self.add_button(vbox, 'Switch', ['switch']) do |arr|
            arr.clear
            Commands::Switch.show(@dialog, @model, []) do |command|
              self.copy_arr(arr, command)
            end
          end
          
          #Wait
          self.add_button(vbox, 'Wait', ['wait']) do |arr|
            arr.clear
            Wait.show(@dialog, []) do |command|
              self.copy_arr(arr, command)
            end
          end

          
          #Anime
          self.add_button(vbox, 'Anime', ['anime']) do |arr|
            EventEditor::Route::AnimeDialog.show(@dialog) do |move, stay|
              if move == :cancel
                arr.clear
              else
                arr << move
                arr << stay
              end
            end
          end

          #Pass
          self.add_button(vbox, 'Pass', ['pass']) do |arr|
            EventEditor::Route::PassDialog.show(@dialog) do |pass_tile, pass_character, pass_event|
              if pass_tile == :cancel
                arr.clear
              else
                arr << pass_tile
                arr << pass_character
                arr << pass_event
              end
            end
          end
          
          #Move Wait
          self.add_button(vbox, 'Move Wait', ['move_wait']) do |arr|
            EventEditor::Route::MoveWaitDialog.show(@dialog) do |value|
              if value == :cancel
                arr.clear
              else
                arr << value
              end
            end
          end
          
          self.add_button(vbox, 'Dir Fix', ['dir_fix'])
          self.add_button(vbox, 'Dir Free', ['dir_free'])
          self.add_button(vbox, "Speed Up", ['speed_up'])
          self.add_button(vbox, "Speed Down", ['speed_down'])
          
          #SetSpeed
          self.add_button(vbox, 'Set Speed', ['set_speed']) do |arr|
            EventEditor::Route::SetSpeedDialog.show(@dialog) do |value|
              if value == :cancel
                arr.clear
              else
                arr << value
              end
            end
          end
          
          self.add_button(vbox, "Visible", ['visible'])
          self.add_button(vbox, "Invisible", ['invisible'])
          box.add(vbox)
          
          vbox = Gtk::VBox.new(true, 2)
          box.add(vbox)

          #Play SE
          self.add_button(vbox, 'Play SE', ['play_se']) do |arr|
            arr.clear
            PlaySe.show(@dialog, []) do |command|
              self.copy_arr(arr, command)
            end
          end
          
          return box
        end
        
        def self.refresh_list(arr)
          @list_model.clear
          
          iter = @list_model.append
          iter[0] = "* "
          iter[1] = ""
          @last_iter = iter
          
          arr.each do |command|
            self.add_command(command)
          end
          
          @list_box.selection.select_iter(@last_iter)
          
          return arr
        end
        
        def self.get_route_arr
          arr = []
          iter = @list_model.iter_first
          begin
            arr << iter[1] if iter != @last_iter
          end while iter.next!
          return arr
        end
        
        def self.static_command
          arr = self.get_route_arr
          return arr, @route_skip_check.active?, @route_repeat_check.active?
        end

        def self.load(edit_command)
          if @dynamic
            if edit_command.empty?
              self.refresh_list([])
              @wait_check.active = true
              @route_skip_check.active = false
              @route_repeat_check.active = false
            else
              @event_combobox.select(edit_command[1])
              self.refresh_list(edit_command[5])
              @route_skip_check.active = edit_command[2]
              @route_repeat_check.active = edit_command[3]
              @wait_check.active = edit_command[4]
            end
          else
            self.refresh_list(@model.selected_event_page['route'])
            @route_skip_check.active = @model.selected_event_page['status']['route_skip']
            @route_repeat_check.active = @model.selected_event_page['status']['route_repeat']
          end
        end
        
        def self.command
          arr = self.get_route_arr
          return 'route', @event_combobox.selected_data, @route_skip_check.active?, @route_repeat_check.active?, @wait_check.active?, arr
        end
        
        def self.command_to_s(model, args, margin = "")
          name = '[<span color="red">invalid</span>]'
          model.event_select_list.each do |t|
            if t[1] == args[1]
              name = "[ " + t[0] + " ]"
              break
            end
          end
        
          t1 = " " + (args[2] ? "Skip" : "")
          t2 = " " + (args[3] ? "Repeat" : "")
          t3 = " " + (args[4] ? "Wait" : "")
        
          s1 = '<span color="darkgreen"><b>Route:</b> ' + name + t1 + t2 + t3
          s2 = '</span>'

          args[5].each do |value|
            s1 += "\n " + margin + " * " + self.get_command_name(value)
          end
          return s1 + s2
        end
        
        def self.icon
          return @@icon
        end
      end
  end
end